﻿using System;
using UnityEngine;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System.Reflection;
using System.IO;

namespace Jinndev.Json {

    public static class JsonUtil {

        internal class IgnorePropertyResolver : DefaultContractResolver {
            protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) {
                JsonProperty prop = base.CreateProperty(member, memberSerialization);
                prop.Ignored = member is PropertyInfo;
                return prop;
            }
        }
        public static readonly IContractResolver IgnoreProperty = new IgnorePropertyResolver();

        public static readonly JsonSerializerSettings Pretty = new JsonSerializerSettings {
            Formatting = Formatting.Indented
        };

        public static JsonSerializer GetSerializer(bool ignoreProperty, bool stringEnum) {
            var serializer = new JsonSerializer();
            if (ignoreProperty) {
                serializer.ContractResolver = IgnoreProperty;
            }
            if (stringEnum) {
                serializer.Converters.Add(new StringEnumConverter());
            }
            return serializer;
        }

        public static TValue Deserialize<TValue>(string json, JsonSerializerSettings setting = null) {
            return JsonConvert.DeserializeObject<TValue>(json, setting);
        }

        public static object Deserialize(string json, Type type, JsonSerializerSettings setting = null) {
            return JsonConvert.DeserializeObject(json, type, setting);
        }

        public static string Serialize(object value, Type type, JsonSerializerSettings setting = null) {
            return JsonConvert.SerializeObject(value, type, setting);
        }

        public static string Serialize(object value, JsonSerializerSettings setting = null) {
            return JsonConvert.SerializeObject(value, setting);
        }

        public static string ToJsonString(object obj, bool prettyPrint = false, bool ignoreProperty = true, bool stringEnum = true) {
            var settings = new JsonSerializerSettings {
                Formatting = prettyPrint ? Formatting.Indented : Formatting.None
            };
            if (ignoreProperty) {
                settings.ContractResolver = IgnoreProperty;
            }
            if (stringEnum) {
                settings.Converters.Add(new StringEnumConverter());
            }
            return JsonConvert.SerializeObject(obj, settings);
        }

        public static string ToString(JContainer json, bool prettyPrint = false) {
            return json.ToString(prettyPrint ? Formatting.Indented : Formatting.None);
        }

        public static string ToTabIndentString(JContainer json) {
            JsonSerializer serializer = new JsonSerializer {
                Formatting = Formatting.Indented
            };

            // 自定义格式
            StringWriter writer = new StringWriter();
            JsonTextWriter jsonWriter = new JsonTextWriter(writer);
            jsonWriter.IndentChar = '\t';
            jsonWriter.Indentation = 1;

            serializer.Serialize(jsonWriter, json);
            return writer.ToString();
        }

        public static bool IsNull(JToken token) {
            return token == null || token.Type == JTokenType.Null;
        }

        public static void AddObject(JObject json, string key, object value) {
            if (value is JObject) {
                json.Add(key, value as JObject);
            }
            else if (value is JArray) {
                json.Add(key, value as JArray);
            }
            else if (value.GetType().IsValueType) {
                json.Add(key, new JValue(value));
            }
            else if (value.GetType().IsArray) {
                json.Add(key, JArray.FromObject(value));
            }
            else {
                json.Add(key, JObject.FromObject(value));
            }
        }

        public static JObject ParseJsonObject(string text) {
            return JObject.Parse(text);
        }

        public static JArray ParseJsonArray(string text) {
            return JArray.Parse(text);
        }

        public static T GetValue<T>(JToken json, string key, T defaultValue = default) {
            if (json != null) {
                JToken token = json.SelectToken(key);
                if (!IsNull(token)) {
                    return token.Value<T>();
                }
            }
            return defaultValue;
        }

        public static JToken GetJson(JToken json, object key) {
            if (json != null) {
                return json.SelectToken(key.ToString());
            }
            return null;
        }

        public static JObject GetJsonObject(JToken json, object key) {
            if (json != null) {
                JToken token = json.SelectToken(key.ToString());
                if (!IsNull(token)) {
                    return token.Value<JObject>();
                }
            }
            return null;
        }

        public static JArray GetJsonArray(JToken json, object key) {
            if (json != null) {
                JToken token = json.SelectToken(key.ToString());
                if (!IsNull(token)) {
                    if (token.Type == JTokenType.Array) {
                        return token.Value<JArray>();
                    }
                }
            }
            return null;
        }

        public static string GetString(JToken json, string key, string defaultValue = null) {
            if (json != null) {
                JToken token = json.SelectToken(key);
                if (!IsNull(token)) {
                    return token.Value<string>();
                }
            }
            return defaultValue;
        }

        public static int GetInt(JToken json, string key, int defaultValue = 0) {
            if (json != null) {
                JToken token = json.SelectToken(key);
                if (!IsNull(token)) {
                    return token.Value<int>();
                }
            }
            return defaultValue;
        }

        public static float GetFloat(JToken json, string key, float defaultValue = 0) {
            if (json != null) {
                JToken token = json.SelectToken(key);
                if (!IsNull(token)) {
                    return token.Value<float>();
                }
            }
            return defaultValue;
        }

        public static double GetDouble(JToken json, string key, double defaultValue = 0) {
            if (json != null) {
                JToken token = json.SelectToken(key);
                if (!IsNull(token)) {
                    return token.Value<double>();
                }
            }
            return defaultValue;
        }

        public static long GetLong(JToken json, string key, long defaultValue = 0) {
            if (json != null) {
                JToken token = json.SelectToken(key);
                if (!IsNull(token)) {
                    return token.Value<long>();
                }
            }
            return defaultValue;
        }

        public static bool GetBool(JToken json, string key, bool defaultValue = false) {
            if (json != null) {
                JToken token = json.SelectToken(key);
                if (!IsNull(token)) {
                    return token.Value<bool>();
                }
            }
            return defaultValue;
        }

        public static byte GetByte(JToken json, string key, byte defaultValue = 0) {
            if (json != null) {
                JToken token = json.SelectToken(key);
                if (!IsNull(token)) {
                    return token.Value<byte>();
                }
            }
            return defaultValue;
        }


    }

}
